package config;

import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;

public class ConfigBuilder {

	private Document doc;
	private XPath xpath;

	public ConfigBuilder(InputStream inputStream) {
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(inputStream);

			XPathFactory xpathFactory = XPathFactory.newInstance();
			XPath xpath = xpathFactory.newXPath();

			this.doc = doc;
			this.xpath = xpath;

		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}

	public Config parse() {
		try {
			Config config = new Config();
			parseSouce(config);
			parseTarget(config);
			return config;
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}

	private void parseSouce(Config config) {
		ConfigSection source = new ConfigSection(xpath, doc);
		source.parse("/configuration/source");
		
		ConfigSection queryTableNames = new ConfigSection(xpath, source.getNode());
		queryTableNames.parse("queryTableNames");
		
		ConfigSection queryColumns = new ConfigSection(xpath, source.getNode());
		queryColumns.parse("queryColumns");
		
		ConfigSection queryPkColumns = new ConfigSection(xpath, source.getNode());
		queryPkColumns.parse("queryPkColumns");
		
		ConfigSection queryIndexs = new ConfigSection(xpath,source.getNode());
		queryIndexs.parse("queryIndexs");
		
		ConfigSection querySequences = new ConfigSection(xpath,source.getNode());
		querySequences.parse("querySequences");
		
		ConfigSection dbTypes = new ConfigSection(xpath, source.getNode());
		dbTypes.parse("dbTypes");
		
		List<ConfigSection> types = dbTypes.getChildSection();
		Properties properties = new Properties();
		for(ConfigSection section : types){
			Properties p = section.getAttributes();
			properties.put(p.getProperty("name"), p.getProperty("value"));
		}
		
		config.setSourceDbTypes(properties);
		config.setSqlTplQueryTableNames(queryTableNames.getBody());
		config.setSqlTplQueryColumns(queryColumns.getBody());
		config.setSqlTplQueryPkColumns(queryPkColumns.getBody());
		config.setSqlTplQueryIndex(queryIndexs.getBody());
		config.setSqlTplQuerySequences(querySequences.getBody());
	}

	private void parseTarget(Config config) {
		ConfigSection target = new ConfigSection(xpath, doc);
		target.parse("/configuration/target");
		
		ConfigSection dbTypes = new ConfigSection(xpath, target.getNode());
		dbTypes.parse("dbTypes");
		
		ConfigSection dropTable = new ConfigSection(xpath, target.getNode());
		dropTable.parse("dropTable");
		
		ConfigSection createTable = new ConfigSection(xpath,target.getNode());
		createTable.parse("createTable");
		
		ConfigSection columnDefine = new ConfigSection(xpath,target.getNode());
		columnDefine.parse("columnDefine");
		
		ConfigSection createComments = new ConfigSection(xpath,target.getNode());
		createComments.parse("createComments");
		
		ConfigSection createPk = new ConfigSection(xpath,target.getNode());
		createPk.parse("createPk");
		
		ConfigSection createIndex = new ConfigSection(xpath,target.getNode());
		createIndex.parse("createIndex");
		
		List<ConfigSection> types = dbTypes.getChildSection();
		Properties properties = new Properties();
		for(ConfigSection section : types){
			Properties p = section.getAttributes();
			properties.put(p.getProperty("name"), p.getProperty("value"));
		}
		
		config.setTargetDbTypes(properties);
		config.setSqlTplCreateTable(createTable.getBody());
		config.setSqlTplColumnDefine(columnDefine.getBody());
		config.setSqlTplCreateComments(createComments.getBody());
		config.setSqlTplCreatePk(createPk.getBody());
		config.setSqlTplCreateIndex(createIndex.getBody());
		config.setSqlTplDropTable(dropTable.getBody());
	}
}
